#pragma once

#include <sqlite3.h>
#include <string>
#include <vector>
#include <filesystem>
#include <fmtlog/fmtlog.h>


namespace MY_MQ
{
    
class sqliteHelper
{
    sqlite3* _db_hander;
public:
    using sqlite_callback = int (*)(void*, int, char**, char**);
    sqliteHelper();
    sqliteHelper(const std::string& file_name,uint32_t thread_safe_level = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
    ~sqliteHelper();

    bool open(const std::string& file_name,uint32_t thread_safe_level = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
    bool close();
    static bool deleteSqlite(const std::string& path);
    static bool IsExist(const std::string& path);
    bool exec(const std::string& sql, sqlite_callback cb = nullptr,void *args =nullptr);
    //启动/提交/回滚事务
    bool begin();
    bool commit();
    bool rollback(const std::string& point );
    bool savepoint(const std::string& point);
};
sqliteHelper::sqliteHelper()
: _db_hander(nullptr)
{
    
}
inline sqliteHelper::sqliteHelper(const std::string &file_name, uint32_t thread_safe_level)
:_db_hander(nullptr)
{
    open(file_name, thread_safe_level);
}
bool sqliteHelper::IsExist(const std::string &path)
{
    return std::filesystem::exists(path);
}

inline bool sqliteHelper::exec(const std::string &sql, sqlite_callback cb, void *args)
{
    if(sqlite3_exec(_db_hander, (sql+";").c_str(), cb, args, nullptr) != SQLITE_OK)
    {
        loge("exec sql failed, sql:{},errMsg {}", sql, sqlite3_errmsg(_db_hander));
        return false;
    }
    return true;
}


bool sqliteHelper::deleteSqlite(const std::string& path)
{
    return std::filesystem::remove(path);
}
bool sqliteHelper::open(const std::string& file_name,uint32_t thread_safe_level)
{
    int ret = sqlite3_open_v2(file_name.c_str(), &_db_hander, thread_safe_level, nullptr);
    if (ret != SQLITE_OK)
    {
        loge("open sqlite3 db failed, errcode:{},errMsg {}", ret, sqlite3_errmsg(_db_hander));    
        sqlite3_close(_db_hander);
        _db_hander = nullptr;
        return false;
    }
    return true;
}

bool sqliteHelper::close()
{
    if (_db_hander && sqlite3_close(_db_hander) != SQLITE_OK)
    {
        loge("close sqlite3 db failed, ,errMsg {}", sqlite3_errmsg(_db_hander));    
        return false;
    }
    _db_hander = nullptr;
    return true;
}
bool sqliteHelper::begin()
{
    return exec("begin", nullptr, nullptr);
}

bool sqliteHelper::commit()
{
    return exec("commit ", nullptr, nullptr);
}

bool sqliteHelper::rollback(const std::string& point)
{
    return exec(("rollback " + point).c_str(), nullptr, nullptr);
}

inline bool sqliteHelper::savepoint(const std::string &point)
{
    return exec(("savepoint " + point).c_str(), nullptr, nullptr);
}

sqliteHelper::~sqliteHelper()
{
    close();
}
  
} 
